﻿namespace Fiddler
{
    using Microsoft.Win32;
    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Drawing;
    using System.Globalization;
    using System.IO;
    using System.IO.Compression;
    using System.Net;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Security;
    using System.Security.Authentication;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Web;
    using System.Windows.Forms;
    using Xceed.Compression;
    using Xceed.Compression.Formats;
    using Xceed.FileSystem;
    using Xceed.Zip;

    public static class Utilities
    {
        private const int CB_SETCUEBANNER = 0x1703;
        private const int EM_SETCUEBANNER = 0x1501;
        internal const int MOD_ALT = 1;
        internal const int MOD_CONTROL = 2;
        internal const int MOD_SHIFT = 4;
        internal const int MOD_WIN = 8;
        private static Encoding[] sniffableEncodings = new Encoding[] { Encoding.UTF32, Encoding.BigEndianUnicode, Encoding.Unicode, Encoding.UTF8 };
        internal const int SW_HIDE = 0;
        internal const int SW_RESTORE = 9;
        internal const int SW_SHOW = 5;
        internal const int SW_SHOWNA = 8;
        internal const int WM_COPYDATA = 0x4a;
        internal const int WM_HOTKEY = 0x312;
        internal const int WM_SHOWWINDOW = 0x18;
        internal const int WM_SIZE = 5;

        private static void _DecodeInOrder(string sOrder, bool bAllowChunks, ref byte[] arrBody)
        {
            if (!string.IsNullOrEmpty(sOrder))
            {
                string[] strArray = sOrder.Split(new char[] { ',' });
                for (int i = strArray.Length - 1; i >= 0; i--)
                {
                    string str = strArray[i].Trim();
                    string str2 = str;
                    if (str2 == null)
                    {
                        goto Label_00E5;
                    }
                    if (!(str2 == "gzip"))
                    {
                        if (str2 == "deflate")
                        {
                            goto Label_0082;
                        }
                        if (str2 == "bzip2")
                        {
                            goto Label_008D;
                        }
                        if (str2 == "chunked")
                        {
                            goto Label_0098;
                        }
                        goto Label_00E5;
                    }
                    arrBody = GzipExpand(arrBody);
                    goto Label_0103;
                Label_0082:
                    arrBody = DeflaterExpand(arrBody);
                    goto Label_0103;
                Label_008D:
                    arrBody = bzip2Expand(arrBody);
                    goto Label_0103;
                Label_0098:
                    if (bAllowChunks)
                    {
                        if (i != 0)
                        {
                            FiddlerApplication.Log.LogFormat("!Chunked Encoding must be the LAST Transfer-Encoding applied!", new object[] { sOrder });
                        }
                        arrBody = doUnchunk(arrBody);
                    }
                    FiddlerApplication.Log.LogFormat("!Chunked encoding is permitted only in the Transfer-Encoding header. Content-Encoding: {0}", new object[] { str });
                    goto Label_0103;
                Label_00E5: ;
                    FiddlerApplication.Log.LogFormat("!Cannot decode HTTP response using Encoding: {0}", new object[] { str });
                Label_0103: ;
                }
            }
        }

        private static void _WriteChunkSizeToStream(MemoryStream oMS, int iLen)
        {
            string s = iLen.ToString("x");
            byte[] bytes = Encoding.ASCII.GetBytes(s);
            oMS.Write(bytes, 0, bytes.Length);
        }

        private static void _WriteCRLFToStream(MemoryStream oMS)
        {
            oMS.WriteByte(13);
            oMS.WriteByte(10);
        }

        internal static void activateTabByTitle(string sName, TabControl tabSet)
        {
            foreach (TabPage page in tabSet.TabPages)
            {
                if (string.Equals(page.Text, sName, StringComparison.OrdinalIgnoreCase))
                {
                    tabSet.SelectedTab = page;
                    break;
                }
            }
        }

        public static void AdjustFontSize(Control c, float flSize)
        {
            if (c.Font.Size != flSize)
            {
                c.Font = new Font(c.Font.FontFamily, flSize);
            }
        }

        public static bool areOriginsEquivalent(string sOrigin1, string sOrigin2, int iDefaultPort)
        {
            string str;
            string str3;
            if (string.Equals(sOrigin1, sOrigin2, StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }
            int iPort = iDefaultPort;
            CrackHostAndPort(sOrigin1, out str, ref iPort);
            string a = str + ":" + iPort.ToString();
            iPort = iDefaultPort;
            CrackHostAndPort(sOrigin2, out str3, ref iPort);
            string b = str3 + ":" + iPort.ToString();
            return string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
        }

        internal static bool arrayContainsNonText(byte[] arrIn)
        {
            if (arrIn != null)
            {
                for (int i = 0; i < arrIn.Length; i++)
                {
                    if (arrIn[i] == 0)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        [CodeDescription("Returns a string representing a Hex view of a byte array. Slow.")]
        public static string ByteArrayToHexView(byte[] inArr, int iBytesPerLine)
        {
            return ByteArrayToHexView(inArr, iBytesPerLine, inArr.Length, true);
        }

        [CodeDescription("Returns a string representing a Hex view of a byte array. PERF: Slow.")]
        public static string ByteArrayToHexView(byte[] inArr, int iBytesPerLine, int iMaxByteCount)
        {
            return ByteArrayToHexView(inArr, iBytesPerLine, iMaxByteCount, true);
        }

        [CodeDescription("Returns a string representing a Hex view of a byte array. PERF: Slow.")]
        public static string ByteArrayToHexView(byte[] inArr, int iBytesPerLine, int iMaxByteCount, bool bShowASCII)
        {
            if ((inArr == null) || (inArr.Length == 0))
            {
                return string.Empty;
            }
            if ((iBytesPerLine < 1) || (iMaxByteCount < 1))
            {
                return string.Empty;
            }
            iMaxByteCount = Math.Min(iMaxByteCount, inArr.Length);
            StringBuilder builder = new StringBuilder(iMaxByteCount * 5);
            int num = 0;
            bool flag = false;
            while (num < iMaxByteCount)
            {
                int num2 = Math.Min(iBytesPerLine, iMaxByteCount - num);
                flag = num2 < iBytesPerLine;
                for (int i = 0; i < num2; i++)
                {
                    builder.Append(inArr[num + i].ToString("X2"));
                    builder.Append(" ");
                }
                if (flag)
                {
                    builder.Append(new string(' ', 3 * (iBytesPerLine - num2)));
                }
                if (bShowASCII)
                {
                    builder.Append(" ");
                    for (int j = 0; j < num2; j++)
                    {
                        if (inArr[num + j] < 0x20)
                        {
                            builder.Append(".");
                        }
                        else
                        {
                            builder.Append((char)inArr[num + j]);
                        }
                    }
                    if (flag)
                    {
                        builder.Append(new string(' ', iBytesPerLine - num2));
                    }
                }
                builder.Append("\r\n");
                num += iBytesPerLine;
            }
            return builder.ToString();
        }

        [CodeDescription("Returns a string representing a Hex stream of a byte array. Slow.")]
        public static string ByteArrayToString(byte[] inArr)
        {
            if (inArr == null)
            {
                return "null";
            }
            if (inArr.Length == 0)
            {
                return "empty";
            }
            return BitConverter.ToString(inArr).Replace('-', ' ');
        }

        [CodeDescription("Returns a byte[] representing the bzip2'd representation of writeData[]")]
        public static byte[] bzip2Compress(byte[] writeData)
        {
            if ((writeData == null) || (writeData.Length == 0))
            {
                return new byte[0];
            }
            try
            {
                MemoryStream inner = new MemoryStream();
                using (ZLibCompressedStream stream2 = new ZLibCompressedStream(inner, CompressionMethod.BZip2, CompressionLevel.Highest))
                {
                    stream2.Write(writeData, 0, writeData.Length);
                }
                return inner.ToArray();
            }
            catch (Exception exception)
            {
                FiddlerApplication.DoNotifyUser("The content could not be compressed.\n\n" + exception.Message, "Fiddler: BZIP Compression failed");
                return writeData;
            }
        }

        public static byte[] bzip2Expand(byte[] compressedData)
        {
            if ((compressedData == null) || (compressedData.Length == 0))
            {
                return new byte[0];
            }
            try
            {
                MemoryStream inner = new MemoryStream(compressedData);
                MemoryStream stream2 = new MemoryStream(compressedData.Length);
                using (ZLibCompressedStream stream3 = new ZLibCompressedStream(inner, CompressionMethod.BZip2, CompressionLevel.Highest))
                {
                    byte[] buffer = new byte[0x8000];
                    int count = 0;
                    while ((count = stream3.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        stream2.Write(buffer, 0, count);
                    }
                }
                return stream2.ToArray();
            }
            catch (Exception exception)
            {
                FiddlerApplication.DoNotifyUser("The content could not be decompressed.\n\n" + exception.Message, "Fiddler: Inflation failed");
                return new byte[0];
            }
        }

        [CodeDescription("Convert a full path into one that uses environment variables, e.g. %SYSTEM%")]
        public static string CollapsePath(string sPath)
        {
            StringBuilder pszBuf = new StringBuilder(0x103);
            if (PathUnExpandEnvStrings(sPath, pszBuf, pszBuf.Capacity))
            {
                return pszBuf.ToString();
            }
            return sPath;
        }

        public static string CompactPath(string sPath, int iCharLen)
        {
            if (string.IsNullOrEmpty(sPath))
            {
                return string.Empty;
            }
            if (sPath.Length > iCharLen)
            {
                StringBuilder pszOut = new StringBuilder(iCharLen + 1);
                if (PathCompactPathEx(pszOut, sPath, (uint)(iCharLen + 1), 0))
                {
                    return pszOut.ToString();
                }
            }
            return sPath;
        }

        public static int CompareVersions(string sRequiredVersion, Version verTest)
        {
            string[] strArray = sRequiredVersion.Split(new char[] { '.' });
            if (strArray.Length != 4)
            {
                return 5;
            }
            VersionStruct struct2 = new VersionStruct();
            if ((!int.TryParse(strArray[0], NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out struct2.Major) || !int.TryParse(strArray[1], NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out struct2.Minor)) || (!int.TryParse(strArray[2], NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out struct2.Build) || !int.TryParse(strArray[3], NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out struct2.Private)))
            {
                return 6;
            }
            if (struct2.Major > verTest.Major)
            {
                return 4;
            }
            if (verTest.Major > struct2.Major)
            {
                return -4;
            }
            if (struct2.Minor > verTest.Minor)
            {
                return 3;
            }
            if (verTest.Minor > struct2.Minor)
            {
                return -3;
            }
            if (struct2.Build > verTest.Build)
            {
                return 2;
            }
            if (verTest.Build > struct2.Build)
            {
                return -2;
            }
            if (struct2.Private > verTest.Revision)
            {
                return 1;
            }
            if (verTest.Revision > struct2.Private)
            {
                return -1;
            }
            return 0;
        }

        internal static string ContentTypeForFileExtension(string sExtension)
        {
            if ((sExtension == null) || (sExtension.Length < 1))
            {
                return null;
            }
            if (sExtension == ".js")
            {
                return "text/javascript";
            }
            if (sExtension == ".css")
            {
                return "text/css";
            }
            if (sExtension == ".appcache")
            {
                return "text/cache-manifest";
            }
            string str = null;
            string str2 = null;
            try
            {
                RegistryKey key = Registry.ClassesRoot.OpenSubKey(sExtension, RegistryKeyPermissionCheck.ReadSubTree);
                if (key == null)
                {
                    return str;
                }
                str = (string)key.GetValue("Content Type");
                if (string.IsNullOrEmpty(str))
                {
                    str2 = (string)key.GetValue("");
                    if (!string.IsNullOrEmpty(str2))
                    {
                        RegistryKey key2 = Registry.ClassesRoot.OpenSubKey(str2, RegistryKeyPermissionCheck.ReadSubTree);
                        if (key2 != null)
                        {
                            str = (string)key2.GetValue("Content Type");
                            key2.Close();
                        }
                    }
                }
                key.Close();
            }
            catch (SecurityException)
            {
            }
            return str;
        }

        internal static string ConvertCRAndLFToSpaces(string sIn)
        {
            sIn = sIn.Replace("\r\n", " ");
            sIn = sIn.Replace('\r', ' ');
            sIn = sIn.Replace('\n', ' ');
            return sIn;
        }

        [CodeDescription("Copy a string to the clipboard, with exception handling.")]
        public static bool CopyToClipboard(string sText)
        {
            DataObject oData = new DataObject();
            oData.SetData(DataFormats.Text, sText);
            return CopyToClipboard(oData);
        }

        public static bool CopyToClipboard(DataObject oData)
        {
            try
            {
                Clipboard.SetDataObject(oData, true);
                return true;
            }
            catch (Exception exception)
            {
                FiddlerApplication.DoNotifyUser("Please disable any clipboard monitoring tools and try again.\n\n" + exception.Message, ".NET Framework Bug");
                return true;
            }
        }

        [CodeDescription("This function cracks the Host/Port combo, removing IPV6 brackets if needed.")]
        public static void CrackHostAndPort(string sHostPort, out string sHostname, ref int iPort)
        {
            int length = sHostPort.LastIndexOf(':');
            if ((length > -1) && (length > sHostPort.LastIndexOf(']')))
            {
                if (!int.TryParse(sHostPort.Substring(length + 1), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out iPort))
                {
                    iPort = -1;
                }
                sHostname = sHostPort.Substring(0, length);
            }
            else
            {
                sHostname = sHostPort;
            }
            if (sHostname.StartsWith("[", StringComparison.Ordinal) && sHostname.EndsWith("]", StringComparison.Ordinal))
            {
                sHostname = sHostname.Substring(1, sHostname.Length - 2);
            }
        }

        public static void CreateBundle(string sOutputFile, string[] sInputFiles, string sComment)
        {
            if (System.IO.File.Exists(sOutputFile))
            {
                System.IO.File.Delete(sOutputFile);
            }
            ZipArchive archive = new ZipArchive(new DiskFile(sOutputFile));
            if (FiddlerApplication.Prefs.GetBoolPref("fiddler.SAZ.UseMemoryCache", true))
            {
                archive.TempFolder = new MemoryFolder();
            }
            archive.BeginUpdate();
            if (!string.IsNullOrEmpty(sComment))
            {
                archive.Comment = sComment;
            }
            foreach (string str in sInputFiles)
            {
                if (System.IO.File.Exists(str))
                {
                    new DiskFile(str).CopyTo(archive.RootFolder, true);
                }
            }
            archive.EndUpdate();
            if (FiddlerApplication.Prefs.GetBoolPref("fiddler.saz.ClearCaches", false))
            {
                ZipArchive.ClearCachedZipHandlers();
            }
        }

        [CodeDescription("Returns a byte[] containing a DEFLATE'd copy of writeData[]")]
        public static byte[] DeflaterCompress(byte[] writeData)
        {
            if ((writeData == null) || (writeData.Length == 0))
            {
                return new byte[0];
            }
            try
            {
                return QuickCompression.Compress(writeData, CompressionMethod.Deflated, CompressionLevel.Normal);
            }
            catch (Exception exception)
            {
                FiddlerApplication.DoNotifyUser("The content could not be compressed.\n\n" + exception.Message, "Fiddler: Deflation failed");
                return writeData;
            }
        }

        [CodeDescription("Returns a byte[] representing the INFLATE'd representation of compressedData[]")]
        public static byte[] DeflaterExpand(byte[] compressedData)
        {
            try
            {
                return DeflaterExpandInternal(CONFIG.bUseXceedDecompressForDeflate, compressedData);
            }
            catch (Exception exception)
            {
                FiddlerApplication.DoNotifyUser("The content could not be decompressed.\n\n" + exception.Message, "Fiddler: Inflation failed");
                return new byte[0];
            }
        }

        public static byte[] DeflaterExpandInternal(bool bUseXceed, byte[] compressedData)
        {
            if ((compressedData == null) || (compressedData.Length == 0))
            {
                return new byte[0];
            }
            int offset = 0;
            if (((compressedData.Length > 2) && (compressedData[0] == 120)) && (compressedData[1] == 0x9c))
            {
                offset = 2;
            }
            if (bUseXceed)
            {
                return QuickCompression.Decompress(compressedData, offset, compressedData.Length - offset, CompressionMethod.Deflated, CONFIG.bCheckCompressionIntegrity);
            }
            MemoryStream stream = new MemoryStream(compressedData, offset, compressedData.Length - offset);
            MemoryStream stream2 = new MemoryStream(compressedData.Length);
            using (DeflateStream stream3 = new DeflateStream(stream, CompressionMode.Decompress))
            {
                byte[] buffer = new byte[0x8000];
                int count = 0;
                while ((count = stream3.Read(buffer, 0, buffer.Length)) > 0)
                {
                    stream2.Write(buffer, 0, count);
                }
            }
            return stream2.ToArray();
        }

        internal static string DescribeException(Exception eX)
        {
            StringBuilder builder = new StringBuilder(0x200);
            builder.Append(eX.Message);
            if (eX.InnerException != null)
            {
                builder.AppendFormat(" < {0}", eX.InnerException.Message);
            }
            return builder.ToString();
        }

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll")]
        private static extern bool DestroyIcon(IntPtr handle);
        public static byte[] doChunk(byte[] writeData, int iSuggestedChunkCount)
        {
            if ((writeData == null) || (writeData.Length < 1))
            {
                return Encoding.ASCII.GetBytes("0\r\n\r\n");
            }
            if (iSuggestedChunkCount < 1)
            {
                iSuggestedChunkCount = 1;
            }
            if (iSuggestedChunkCount > writeData.Length)
            {
                iSuggestedChunkCount = writeData.Length;
            }
            MemoryStream oMS = new MemoryStream(writeData.Length + (10 * iSuggestedChunkCount));
            int offset = 0;
            do
            {
                int num2 = writeData.Length - offset;
                int num3 = num2 / iSuggestedChunkCount;
                num3 = Math.Max(1, num3);
                num3 = Math.Min(num2, num3);
                _WriteChunkSizeToStream(oMS, num3);
                _WriteCRLFToStream(oMS);
                oMS.Write(writeData, offset, num3);
                _WriteCRLFToStream(oMS);
                offset += num3;
                iSuggestedChunkCount--;
                if (iSuggestedChunkCount < 1)
                {
                    iSuggestedChunkCount = 1;
                }
            }
            while (offset < writeData.Length);
            _WriteChunkSizeToStream(oMS, 0);
            _WriteCRLFToStream(oMS);
            _WriteCRLFToStream(oMS);
            return oMS.ToArray();
        }

        public static void DoFlash(IntPtr hWnd)
        {
            FLASHWINFO structure = new FLASHWINFO();
            structure.cbSize = Marshal.SizeOf(structure);
            structure.hwnd = hWnd;
            structure.dwFlags = Utilities.FlashWInfo.FLASHW_TIMERNOFG | Utilities.FlashWInfo.FLASHW_TRAY;
            structure.uCount = 0;
            structure.dwTimeout = 0;
            FlashWindowEx(ref structure);
        }

        public static void DoOpenFileWith(string sFilename)
        {
            if (Environment.OSVersion.Version.Major > 5)
            {
                IntPtr zero = IntPtr.Zero;
                if (FiddlerApplication.UI != null)
                {
                    zero = FiddlerApplication.UI.Handle;
                }
                tagOPENASINFO oOAI = new tagOPENASINFO();
                oOAI.cszFile = sFilename;
                oOAI.cszClass = string.Empty;
                oOAI.oaifInFlags = tagOPEN_AS_INFO_FLAGS.OAIF_EXEC | tagOPEN_AS_INFO_FLAGS.OAIF_ALLOW_REGISTRATION;
                SHOpenWithDialog(zero, ref oOAI);
            }
            else
            {
                using (Process.Start("rundll32", "shell32.dll,OpenAs_RunDLL " + sFilename))
                {
                }
            }
        }

        public static byte[] doUnchunk(byte[] writeData)
        {
            if ((writeData == null) || (writeData.Length == 0))
            {
                return new byte[0];
            }
            MemoryStream stream = new MemoryStream(writeData.Length);
            int index = 0;
            bool flag = false;
            while (!flag && (index <= (writeData.Length - 3)))
            {
                int num3;
                string sInput = Encoding.ASCII.GetString(writeData, index, Math.Min(0x40, writeData.Length - index));
                int length = sInput.IndexOf("\r\n", StringComparison.Ordinal);
                if (length <= 0)
                {
                    throw new InvalidDataException("HTTP Error: The chunked content is corrupt. Cannot find Chunk-Length in expected location. Offset: " + index.ToString());
                }
                index += length + 2;
                sInput = sInput.Substring(0, length);
                length = sInput.IndexOf(';');
                if (length > 0)
                {
                    sInput = sInput.Substring(0, length);
                }
                if (!TryHexParse(sInput, out num3))
                {
                    throw new InvalidDataException("HTTP Error: The chunked content is corrupt. Chunk Length was malformed. Offset: " + index.ToString());
                }
                if (num3 == 0)
                {
                    flag = true;
                }
                else
                {
                    if (writeData.Length < (num3 + index))
                    {
                        throw new InvalidDataException("HTTP Error: The chunked entity body is corrupt. The final chunk length is greater than the number of bytes remaining.");
                    }
                    stream.Write(writeData, index, num3);
                    index += num3 + 2;
                }
            }
            if ((!flag && CONFIG.bReportHTTPErrors) && !CONFIG.QuietMode)
            {
                FiddlerApplication.DoNotifyUser("Chunked body did not terminate properly with 0-sized chunk.", "HTTP Protocol Violation");
            }
            byte[] dst = new byte[stream.Length];
            Buffer.BlockCopy(stream.GetBuffer(), 0, dst, 0, dst.Length);
            return dst;
        }

        public static byte[] Dupe(byte[] bIn)
        {
            if (bIn == null)
            {
                return new byte[0];
            }
            byte[] dst = new byte[bIn.Length];
            Buffer.BlockCopy(bIn, 0, dst, 0, bIn.Length);
            return dst;
        }

        public static void EnsureOverwritable(string sFilename)
        {
            if (!Directory.Exists(Path.GetDirectoryName(sFilename)))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(sFilename));
            }
            if (System.IO.File.Exists(sFilename))
            {
                FileAttributes attributes = System.IO.File.GetAttributes(sFilename);
                System.IO.File.SetAttributes(sFilename, attributes & ~(FileAttributes.System | FileAttributes.Hidden | FileAttributes.ReadOnly));
            }
        }

        internal static string EnsurePathIsAbsolute(string sRootPath, string sFilename)
        {
            try
            {
                if (!Path.IsPathRooted(sFilename))
                {
                    sFilename = sRootPath + sFilename;
                }
            }
            catch (Exception)
            {
            }
            return sFilename;
        }

        public static string EnsureUniqueFilename(string sFilename)
        {
            string path = sFilename;
            try
            {
                if (!System.IO.File.Exists(sFilename))
                {
                    return path;
                }
                string directoryName = Path.GetDirectoryName(sFilename);
                string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(sFilename);
                string extension = Path.GetExtension(sFilename);
                int num = 1;
                do
                {
                    path = string.Format(@"{0}\{1}[{2}]{3}", new object[] { directoryName, fileNameWithoutExtension, num.ToString(), extension });
                    num++;
                }
                while (System.IO.File.Exists(path));
            }
            catch
            {
            }
            return path;
        }

        internal static bool FiddlerMeetsVersionRequirement(Assembly assemblyInput, string sWhatType)
        {
            if (!assemblyInput.IsDefined(typeof(RequiredVersionAttribute), false))
            {
                return false;
            }
            RequiredVersionAttribute customAttribute = (RequiredVersionAttribute)Attribute.GetCustomAttribute(assemblyInput, typeof(RequiredVersionAttribute));
            int num = CompareVersions(customAttribute.RequiredVersion, CONFIG.FiddlerVersionInfo);
            if (num > 0)
            {
                FiddlerApplication.DoNotifyUser(string.Format("The {0} in {1} require Fiddler v{2} or later. (You have v{3})\n\nPlease install the latest version of Fiddler from http://getfiddler.com.\n\nCode: {4}", new object[] { sWhatType, assemblyInput.CodeBase, customAttribute.RequiredVersion, CONFIG.FiddlerVersionInfo, num }), "Extension Not Loaded");
                return false;
            }
            return true;
        }

        internal static string FileExtensionForMIMEType(string sMIME)
        {
            sMIME = sMIME.ToLower();
            switch (sMIME)
            {
                case "text/css":
                    return ".css";

                case "text/html":
                    return ".htm";

                case "text/javascript":
                case "application/javascript":
                case "application/x-javascript":
                    return ".js";

                case "text/cache-manifest":
                    return ".appcache";

                case "image/jpg":
                case "image/jpeg":
                    return ".jpg";

                case "image/gif":
                    return ".gif";

                case "image/png":
                    return ".png";

                case "image/x-icon":
                    return ".ico";

                case "text/xml":
                    return ".xml";

                case "video/x-flv":
                    return ".flv";

                case "video/mp4":
                    return ".mp4";

                case "text/plain":
                case "application/octet-stream":
                    return ".txt";
            }
            try
            {
                RegistryKey key = Registry.ClassesRoot.OpenSubKey(string.Format(@"\MIME\Database\Content Type\{0}", sMIME), RegistryKeyPermissionCheck.ReadSubTree);
                if (key != null)
                {
                    string str = (string)key.GetValue("Extension");
                    key.Close();
                    if (!string.IsNullOrEmpty(str))
                    {
                        return str;
                    }
                }
            }
            catch
            {
            }
            if (sMIME.EndsWith("+xml"))
            {
                return ".xml";
            }
            return ".txt";
        }

        [DllImport("user32.dll")]
        internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll")]
        private static extern bool FlashWindowEx(ref FLASHWINFO pwfi);
        internal static System.Drawing.Color GetColorFromString(string sColor)
        {
            if ((sColor.Length == 7) && (sColor[0] == '#'))
            {
                return System.Drawing.Color.FromArgb(Convert.ToInt32(sColor.Substring(1, 2), 0x10), Convert.ToInt32(sColor.Substring(3, 2), 0x10), Convert.ToInt32(sColor.Substring(5, 2), 0x10));
            }
            return System.Drawing.Color.FromName(sColor);
        }

        private static COMBOBOXINFO GetComboBoxInfo(Control control)
        {
            COMBOBOXINFO structure = new COMBOBOXINFO();
            structure.cbSize = Marshal.SizeOf(structure);
            if (!GetComboBoxInfo(control.Handle, ref structure))
            {
                Marshal.GetLastWin32Error();
            }
            return structure;
        }

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool GetComboBoxInfo(IntPtr hwnd, ref COMBOBOXINFO pcbi);
        public static string GetCommaTokenValue(string sString, string sTokenName)
        {
            string str = null;
            if ((sString != null) && (sString.Length > 0))
            {
                System.Text.RegularExpressions.Match match = new Regex(sTokenName + "\\s?=?\\s?[\"]?(?<TokenValue>[^\";,]*)", RegexOptions.IgnoreCase).Match(sString);
                if (match.Success && (match.Groups["TokenValue"] != null))
                {
                    str = match.Groups["TokenValue"].Value;
                }
            }
            return str;
        }

        public static System.Drawing.Color GetContrastingTextColor(System.Drawing.Color clrBackground)
        {
            clrBackground.ToArgb();
            if (Math.Sqrt((((clrBackground.R * clrBackground.R) * 0.299) + ((clrBackground.G * clrBackground.G) * 0.587)) + ((clrBackground.B * clrBackground.B) * 0.114)) <= 130.0)
            {
                return System.Drawing.Color.White;
            }
            return System.Drawing.Color.FromArgb(1);
        }

        [CodeDescription("Gets (via Headers or Sniff) the provided body's text Encoding. Returns CONFIG.oHeaderEncoding (usually UTF-8) if unknown. Potentially slow.")]
        public static Encoding getEntityBodyEncoding(HTTPHeaders oHeaders, byte[] oBody)
        {
            if (oHeaders != null)
            {
                string tokenValue = oHeaders.GetTokenValue("Content-Type", "charset");
                if (tokenValue != null)
                {
                    try
                    {
                        return Encoding.GetEncoding(tokenValue);
                    }
                    catch (Exception)
                    {
                    }
                }
            }
            Encoding oHeaderEncoding = CONFIG.oHeaderEncoding;
            if ((oBody != null) && (oBody.Length >= 2))
            {
                foreach (Encoding encoding2 in sniffableEncodings)
                {
                    byte[] preamble = encoding2.GetPreamble();
                    if (oBody.Length >= preamble.Length)
                    {
                        bool flag = preamble.Length > 0;
                        for (int i = 0; i < preamble.Length; i++)
                        {
                            if (preamble[i] != oBody[i])
                            {
                                flag = false;
                                break;
                            }
                        }
                        if (flag)
                        {
                            oHeaderEncoding = encoding2;
                            break;
                        }
                    }
                }
                if ((oHeaders != null) && oHeaders.ExistsAndContains("Content-Type", "html"))
                {
                    string input = oHeaderEncoding.GetString(oBody, 0, Math.Min(0x1000, oBody.Length));
                    MatchCollection matchs = new Regex("<meta\\s.*charset\\s*=\\s*['\\\"]?(?<thecharset>[^'>\\\"]*)", RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase).Matches(input);
                    if ((matchs.Count <= 0) || (matchs[0].Groups.Count <= 0))
                    {
                        return oHeaderEncoding;
                    }
                    string name = null;
                    try
                    {
                        name = matchs[0].Groups[1].Value;
                        oHeaderEncoding = Encoding.GetEncoding(name);
                    }
                    catch (Exception)
                    {
                        if (CONFIG.bReportHTTPLintErrors)
                        {
                            FiddlerApplication.Log.LogFormat("HTML content specified a CHARSET that did not parse. Value was: {0}", new object[] { name });
                        }
                    }
                }
            }
            return oHeaderEncoding;
        }

        [CodeDescription("Run an executable, wait for it to exit, and return its output as a string.")]
        public static string GetExecutableOutput(string sExecute, string sParams, out int iExitCode)
        {
            iExitCode = -999;
            StringBuilder builder = new StringBuilder();
            builder.Append("Results from " + sExecute + " " + sParams + "\r\n\r\n");
            try
            {
                string str;
                Process process = new Process();
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = false;
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.FileName = sExecute;
                process.StartInfo.Arguments = sParams;
                process.Start();
                while ((str = process.StandardOutput.ReadLine()) != null)
                {
                    str = str.TrimEnd(new char[0]);
                    if (str != string.Empty)
                    {
                        builder.Append(str + "\r\n");
                    }
                }
                iExitCode = process.ExitCode;
                process.Dispose();
            }
            catch (Exception exception)
            {
                builder.Append("Exception thrown: " + exception.ToString() + "\r\n" + exception.StackTrace.ToString());
            }
            builder.Append("-------------------------------------------\r\n");
            return builder.ToString();
        }

        internal static string GetFirstLocalResponse(string sFilename)
        {
            sFilename = TrimAfter(sFilename, '?');
            try
            {
                if (!Path.IsPathRooted(sFilename))
                {
                    string str = sFilename;
                    sFilename = CONFIG.GetPath("TemplateResponses") + str;
                    if (!System.IO.File.Exists(sFilename))
                    {
                        sFilename = CONFIG.GetPath("Responses") + str;
                    }
                }
            }
            catch (Exception)
            {
            }
            return sFilename;
        }

        internal static Icon GetIconFromImage(Image oBMP)
        {
            IntPtr hicon = ((Bitmap)oBMP).GetHicon();
            Icon icon = (Icon)Icon.FromHandle(hicon).Clone();
            DestroyIcon(hicon);
            return icon;
        }

        internal static object GetOSVerString()
        {
            return Environment.OSVersion.VersionString.Replace("Microsoft Windows ", "Win").Replace("Service Pack ", "SP");
        }

        [CodeDescription("Returns an bool from the registry, or bDefault if the registry key is missing or cannot be used as an bool.")]
        public static bool GetRegistryBool(RegistryKey oReg, string sName, bool bDefault)
        {
            bool flag = bDefault;
            object obj2 = oReg.GetValue(sName);
            if (obj2 is int)
            {
                return (1 == ((int)obj2));
            }
            if (obj2 is string)
            {
                flag = string.Equals(obj2 as string, "true", StringComparison.OrdinalIgnoreCase);
            }
            return flag;
        }

        [CodeDescription("Returns an float from the registry, or flDefault if the registry key is missing or cannot be used as an float.")]
        public static float GetRegistryFloat(RegistryKey oReg, string sName, float flDefault)
        {
            float result = flDefault;
            object obj2 = oReg.GetValue(sName);
            if (obj2 is int)
            {
                return (float)obj2;
            }
            if ((obj2 is string) && !float.TryParse((string)obj2, NumberStyles.Float, CultureInfo.InvariantCulture, out result))
            {
                result = flDefault;
            }
            return result;
        }

        [CodeDescription("Returns an integer from the registry, or iDefault if the registry key is missing or cannot be used as an integer.")]
        public static int GetRegistryInt(RegistryKey oReg, string sName, int iDefault)
        {
            int result = iDefault;
            object obj2 = oReg.GetValue(sName);
            if (obj2 is int)
            {
                return (int)obj2;
            }
            if ((obj2 is string) && !int.TryParse((string)obj2, out result))
            {
                return iDefault;
            }
            return result;
        }

        [CodeDescription("Gets (via Headers or Sniff) the Response Text Encoding. Returns CONFIG.oHeaderEncoding (usually UTF-8) if unknown. Potentially slow.")]
        public static Encoding getResponseBodyEncoding(Session oSession)
        {
            if (oSession == null)
            {
                return CONFIG.oHeaderEncoding;
            }
            if (!oSession.bHasResponse)
            {
                return CONFIG.oHeaderEncoding;
            }
            return getEntityBodyEncoding(oSession.oResponse.headers, oSession.responseBodyBytes);
        }

        [CodeDescription("Gets a string from a byte-array, stripping a BOM if present.")]
        public static string GetStringFromArrayRemovingBOM(byte[] arrInput, Encoding oDefaultEncoding)
        {
            if (arrInput == null)
            {
                return string.Empty;
            }
            if (arrInput.Length >= 2)
            {
                foreach (Encoding encoding in sniffableEncodings)
                {
                    byte[] preamble = encoding.GetPreamble();
                    if (arrInput.Length >= preamble.Length)
                    {
                        bool flag = preamble.Length > 0;
                        for (int i = 0; i < preamble.Length; i++)
                        {
                            if (preamble[i] != arrInput[i])
                            {
                                flag = false;
                                break;
                            }
                        }
                        if (flag)
                        {
                            int length = encoding.GetPreamble().Length;
                            return encoding.GetString(arrInput, length, arrInput.Length - length);
                        }
                    }
                }
            }
            return oDefaultEncoding.GetString(arrInput);
        }

        internal static string GetStringFromColor(System.Drawing.Color c)
        {
            if (c.IsNamedColor)
            {
                return c.Name;
            }
            return string.Format("#{0:x2}{1:x2}{2:x2}", c.R, c.G, c.B);
        }

        public static ulong GetTickCount()
        {
            if (Environment.OSVersion.Version.Major > 5)
            {
                return GetTickCount64();
            }
            int tickCount = Environment.TickCount;
            if (tickCount > 0)
            {
                return (ulong)tickCount;
            }
            return ((ulong)0xfffffffeL - (ulong)tickCount);
        }

        [DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]
        private static extern ulong GetTickCount64();
        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll")]
        internal static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
        [DllImport("kernel32.dll", SetLastError = true)]
        internal static extern IntPtr GlobalFree(IntPtr hMem);
        internal static void GlobalFreeIfNonZero(IntPtr hMem)
        {
            if (IntPtr.Zero != hMem)
            {
                GlobalFree(hMem);
            }
        }

        [CodeDescription("Returns a byte[] containing a gzip-compressed copy of writeData[]")]
        public static byte[] GzipCompress(byte[] writeData)
        {
            try
            {
                MemoryStream inner = new MemoryStream();
                using (GZipCompressedStream stream2 = new GZipCompressedStream(inner))
                {
                    stream2.Write(writeData, 0, writeData.Length);
                }
                return inner.ToArray();
            }
            catch (Exception exception)
            {
                FiddlerApplication.DoNotifyUser("The content could not be compressed.\n\n" + exception.Message, "Fiddler: GZip failed");
                return writeData;
            }
        }

        [CodeDescription("Returns a byte[] containing an un-gzipped copy of compressedData[]")]
        public static byte[] GzipExpand(byte[] compressedData)
        {
            try
            {
                return GzipExpandInternal(CONFIG.bUseXceedDecompressForGZIP, compressedData);
            }
            catch (Exception exception)
            {
                FiddlerApplication.DoNotifyUser("The content could not be decompressed.\n\n" + exception.Message, "Fiddler: UnGZip failed");
                return new byte[0];
            }
        }

        public static byte[] GzipExpandInternal(bool bUseXceed, byte[] compressedData)
        {
            if ((compressedData == null) || (compressedData.Length == 0))
            {
                return new byte[0];
            }
            MemoryStream inner = new MemoryStream(compressedData);
            MemoryStream stream2 = new MemoryStream(compressedData.Length);
            if (bUseXceed)
            {
                using (GZipCompressedStream stream3 = new GZipCompressedStream(inner, CompressionLevel.Normal, false, CONFIG.bCheckCompressionIntegrity))
                {
                    byte[] buffer = new byte[0x8000];
                    int count = 0;
                    while ((count = stream3.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        stream2.Write(buffer, 0, count);
                    }
                    goto Label_00AE;
                }
            }
            using (GZipStream stream4 = new GZipStream(inner, CompressionMode.Decompress))
            {
                byte[] buffer2 = new byte[0x8000];
                int num2 = 0;
                while ((num2 = stream4.Read(buffer2, 0, buffer2.Length)) > 0)
                {
                    stream2.Write(buffer2, 0, num2);
                }
            }
        Label_00AE:
            return stream2.ToArray();
        }

        internal static bool HasHeaders(ClientChatter oCC)
        {
            return ((oCC != null) && (null != oCC.headers));
        }

        internal static bool HasHeaders(ServerChatter oSC)
        {
            return ((oSC != null) && (null != oSC.headers));
        }

        public static bool HasMagicBytes(byte[] arrData, string sMagics)
        {
            return HasMagicBytes(arrData, Encoding.ASCII.GetBytes(sMagics));
        }

        public static bool HasMagicBytes(byte[] arrData, byte[] arrMagics)
        {
            if (arrData == null)
            {
                return false;
            }
            if (arrData.Length < arrMagics.Length)
            {
                return false;
            }
            for (int i = 0; i < arrMagics.Length; i++)
            {
                if (arrData[i] != arrMagics[i])
                {
                    return false;
                }
            }
            return true;
        }

        public static string HtmlDecode(string sInput)
        {
            return HttpUtility.HtmlDecode(sInput);
        }

        public static string HtmlEncode(string sInput)
        {
            if (sInput == null)
            {
                return null;
            }
            return HttpUtility.HtmlEncode(sInput);
        }

        [CodeDescription("Returns TRUE if the HTTP Method MAY have a body.")]
        public static bool HTTPMethodAllowsBody(string sMethod)
        {
            if (((!("POST" == sMethod) && !("PUT" == sMethod)) && (!("PROPPATCH" == sMethod) && !("PATCH" == sMethod))) && (!("LOCK" == sMethod) && !("PROPFIND" == sMethod)))
            {
                return ("SEARCH" == sMethod);
            }
            return true;
        }

        [CodeDescription("Returns TRUE if the HTTP Method MUST have a body.")]
        public static bool HTTPMethodRequiresBody(string sMethod)
        {
            if (!("PROPPATCH" == sMethod))
            {
                return ("PATCH" == sMethod);
            }
            return true;
        }

        [CodeDescription("Returns TRUE if a response body is allowed for this responseCode.")]
        public static bool HTTPStatusAllowsBody(int iResponseCode)
        {
            if (((0xcc == iResponseCode) || (0xcd == iResponseCode)) || (0x130 == iResponseCode))
            {
                return false;
            }
            if (iResponseCode > 0x63)
            {
                return (iResponseCode >= 200);
            }
            return true;
        }

        public static IPEndPoint IPEndPointFromHostPortString(string sHostAndPort)
        {
            if (IsNullOrWhiteSpace(sHostAndPort))
            {
                return null;
            }
            sHostAndPort = TrimAfter(sHostAndPort, ';');
            try
            {
                string str;
                int iPort = 80;
                CrackHostAndPort(sHostAndPort, out str, ref iPort);
                return new IPEndPoint(DNSResolver.GetIPAddress(str, true), iPort);
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static IPEndPoint[] IPEndPointListFromHostPortString(string sAllHostAndPorts)
        {
            if (IsNullOrWhiteSpace(sAllHostAndPorts))
            {
                return null;
            }
            string[] strArray = sAllHostAndPorts.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            List<IPEndPoint> list = new List<IPEndPoint>();
            foreach (string str in strArray)
            {
                try
                {
                    string str2;
                    int iPort = 80;
                    CrackHostAndPort(str, out str2, ref iPort);
                    foreach (IPAddress address in DNSResolver.GetIPAddressList(str2, true, null))
                    {
                        list.Add(new IPEndPoint(address, iPort));
                    }
                }
                catch (Exception)
                {
                }
            }
            if (list.Count < 1)
            {
                return null;
            }
            return list.ToArray();
        }

        [CodeDescription("This function attempts to be a ~fast~ way to return an IP from a hoststring that contains an IP-Literal. ")]
        public static IPAddress IPFromString(string sHost)
        {
            for (int i = 0; i < sHost.Length; i++)
            {
                if (((((sHost[i] != '.') && (sHost[i] != ':')) && ((sHost[i] < '0') || (sHost[i] > '9'))) && ((sHost[i] < 'A') || (sHost[i] > 'F'))) && ((sHost[i] < 'a') || (sHost[i] > 'f')))
                {
                    return null;
                }
            }
            if (sHost.EndsWith("."))
            {
                sHost = TrimBeforeLast(sHost, '.');
            }
            try
            {
                return IPAddress.Parse(sHost);
            }
            catch
            {
                return null;
            }
        }

        public static bool IsBinaryMIME(string sContentType)
        {
            if (string.IsNullOrEmpty(sContentType))
            {
                return false;
            }
            if (sContentType.StartsWith("text/", StringComparison.OrdinalIgnoreCase))
            {
                return false;
            }
            if (sContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
            {
                return !sContentType.StartsWith("image/svg+xml", StringComparison.OrdinalIgnoreCase);
            }
            return (sContentType.StartsWith("application/octet", StringComparison.OrdinalIgnoreCase) || (sContentType.StartsWith("application/x-shockwave-flash", StringComparison.OrdinalIgnoreCase) || (sContentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase) || sContentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))));
        }

        public static bool IsBrowserProcessName(string sProcessName)
        {
            if (string.IsNullOrEmpty(sProcessName))
            {
                return false;
            }
            if (((!sProcessName.StartsWith("ie", StringComparison.OrdinalIgnoreCase) && !sProcessName.StartsWith("chrom", StringComparison.OrdinalIgnoreCase)) && (!sProcessName.StartsWith("firefox", StringComparison.OrdinalIgnoreCase) && !sProcessName.StartsWith("opera", StringComparison.OrdinalIgnoreCase))) && !sProcessName.StartsWith("webkit", StringComparison.OrdinalIgnoreCase))
            {
                return sProcessName.StartsWith("safari", StringComparison.OrdinalIgnoreCase);
            }
            return true;
        }

        internal static bool IsChunkedBodyComplete(Session m_session, MemoryStream oData, long iStartAtOffset, out long outStartOfLatestChunk, out long outEndOfEntity)
        {
            return IsChunkedBodyComplete(m_session, oData.GetBuffer(), iStartAtOffset, oData.Length, out outStartOfLatestChunk, out outEndOfEntity);
        }

        internal static bool IsChunkedBodyComplete(Session m_session, byte[] oRawBuffer, long iStartAtOffset, long iEndAtOffset, out long outStartOfLatestChunk, out long outEndOfEntity)
        {
            int index = (int)iStartAtOffset;
            outStartOfLatestChunk = index;
            outEndOfEntity = -1;
            while (index < iEndAtOffset)
            {
                outStartOfLatestChunk = index;
                string sInput = Encoding.ASCII.GetString(oRawBuffer, index, Math.Min(0x40, ((int)iEndAtOffset) - index));
                int length = sInput.IndexOf("\r\n", StringComparison.Ordinal);
                if (length > -1)
                {
                    index += length + 2;
                    sInput = sInput.Substring(0, length);
                }
                else
                {
                    return false;
                }
                length = sInput.IndexOf(';');
                if (length > -1)
                {
                    sInput = sInput.Substring(0, length);
                }
                int iOutput = 0;
                if (!TryHexParse(sInput, out iOutput))
                {
                    SessionFlags flagViolation = (m_session.state <= SessionStates.ReadingRequest) ? SessionFlags.ProtocolViolationInRequest : SessionFlags.ProtocolViolationInResponse;
                    FiddlerApplication.HandleHTTPError(m_session, flagViolation, true, true, "Illegal chunked encoding. '" + sInput + "' is not a hexadecimal number.");
                    return true;
                }
                if (iOutput == 0)
                {
                    bool flag = true;
                    bool flag2 = false;
                    if ((index + 2) <= iEndAtOffset)
                    {
                        for (int i = oRawBuffer[index++]; index <= iEndAtOffset; i = oRawBuffer[index++])
                        {
                            int num5 = i;
                            if (num5 != 10)
                            {
                                if (num5 != 13)
                                {
                                    goto Label_00FA;
                                }
                                flag2 = true;
                            }
                            else if (flag2)
                            {
                                if (flag)
                                {
                                    outEndOfEntity = index;
                                    return true;
                                }
                                flag = true;
                                flag2 = false;
                            }
                            else
                            {
                                flag2 = false;
                                flag = false;
                            }
                            goto Label_0100;
                        Label_00FA:
                            flag2 = false;
                            flag = false;
                        Label_0100: ;
                        }
                    }
                    return false;
                }
                index += iOutput + 2;
            }
            return false;
        }

        internal static bool isHTTP200Array(byte[] arrData)
        {
            return ((((((arrData.Length > 12) && (arrData[0] == 0x48)) && ((arrData[1] == 0x54) && (arrData[2] == 0x54))) && (((arrData[3] == 80) && (arrData[4] == 0x2f)) && ((arrData[5] == 0x31) && (arrData[6] == 0x2e)))) && ((arrData[9] == 50) && (arrData[10] == 0x30))) && (arrData[11] == 0x30));
        }

        internal static bool isHTTP407Array(byte[] arrData)
        {
            return ((((((arrData.Length > 12) && (arrData[0] == 0x48)) && ((arrData[1] == 0x54) && (arrData[2] == 0x54))) && (((arrData[3] == 80) && (arrData[4] == 0x2f)) && ((arrData[5] == 0x31) && (arrData[6] == 0x2e)))) && ((arrData[9] == 0x34) && (arrData[10] == 0x30))) && (arrData[11] == 0x37));
        }

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll")]
        internal static extern bool IsIconic(IntPtr hWnd);
        [CodeDescription("Returns true if True if the sHostAndPort's host is 127.0.0.1, 'localhost', or ::1. Note that list is not complete.")]
        public static bool isLocalhost(string sHostAndPort)
        {
            string str;
            int iPort = 0;
            CrackHostAndPort(sHostAndPort, out str, ref iPort);
            return isLocalhostname(str);
        }

        [CodeDescription("Returns true if True if the sHostname is 127.0.0.1, 'localhost', or ::1. Note that list is not complete.")]
        public static bool isLocalhostname(string sHostname)
        {
            if ((!string.Equals(sHostname, "localhost", StringComparison.OrdinalIgnoreCase) && !string.Equals(sHostname, "localhost.", StringComparison.OrdinalIgnoreCase)) && !string.Equals(sHostname, "127.0.0.1", StringComparison.OrdinalIgnoreCase))
            {
                return string.Equals(sHostname, "::1", StringComparison.OrdinalIgnoreCase);
            }
            return true;
        }

        public static bool IsNullOrEmpty(byte[] bIn)
        {
            return ((bIn == null) || (bIn.Length == 0));
        }

        internal static bool IsNullOrWhiteSpace(string sInput)
        {
            if (sInput != null)
            {
                return (0 == sInput.Trim().Length);
            }
            return true;
        }

        [CodeDescription("Returns false if Hostname contains any dots or colons.")]
        public static bool isPlainHostName(string sHostAndPort)
        {
            string str;
            int iPort = 0;
            CrackHostAndPort(sHostAndPort, out str, ref iPort);
            char[] anyOf = new char[] { '.', ':' };
            return (str.IndexOfAny(anyOf) < 0);
        }

        public static bool IsRedirectStatus(int iResponseCode)
        {
            if (((iResponseCode != 0x12d) && (iResponseCode != 0x12e)) && ((iResponseCode != 0x12f) && (iResponseCode != 0x133)))
            {
                return (iResponseCode == 0x134);
            }
            return true;
        }

        public static bool isUnsupportedEncoding(string sTE, string sCE)
        {
            return ((!string.IsNullOrEmpty(sTE) && (sTE.IndexOf("xpress", StringComparison.OrdinalIgnoreCase) > -1)) || (!string.IsNullOrEmpty(sCE) && (sCE.IndexOf("xpress", StringComparison.OrdinalIgnoreCase) > -1)));
        }

        [DllImport("shell32.dll")]
        public static extern bool IsUserAnAdmin();
        [CodeDescription("ShellExecutes the sURL.")]
        public static bool LaunchHyperlink(string sURL)
        {
            try
            {
                using (Process.Start(sURL))
                {
                }
                return true;
            }
            catch (Exception exception)
            {
                FiddlerApplication.DoNotifyUser("Your web browser is not correctly configured to launch hyperlinks.\n\nTo see this content, visit:\n\t" + sURL + "\n...in your web browser.\n\nError: " + exception.Message, "Error");
            }
            return false;
        }

        public static string[] ObtainFilenames(string sDialogTitle, string sFilter, string sInitialDirectory, bool bAllowMultiple)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Title = sDialogTitle;
            dialog.Multiselect = bAllowMultiple;
            dialog.Filter = sFilter;
            if (!string.IsNullOrEmpty(sInitialDirectory))
            {
                dialog.InitialDirectory = sInitialDirectory;
                dialog.RestoreDirectory = true;
            }
            dialog.CustomPlaces.Add(CONFIG.GetPath("Captures"));
            string[] fileNames = null;
            if (DialogResult.OK == dialog.ShowDialog(FiddlerApplication.UI))
            {
                fileNames = dialog.FileNames;
            }
            dialog.Dispose();
            return fileNames;
        }

        public static string ObtainOpenFilename(string sDialogTitle, string sFilter)
        {
            return ObtainOpenFilename(sDialogTitle, sFilter, null);
        }

        public static string ObtainOpenFilename(string sDialogTitle, string sFilter, string sInitialDirectory)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Title = sDialogTitle;
            dialog.Filter = sFilter;
            if (!string.IsNullOrEmpty(sInitialDirectory))
            {
                dialog.InitialDirectory = sInitialDirectory;
                dialog.RestoreDirectory = true;
            }
            dialog.CustomPlaces.Add(CONFIG.GetPath("Captures"));
            string fileName = null;
            if (DialogResult.OK == dialog.ShowDialog(FiddlerApplication.UI))
            {
                fileName = dialog.FileName;
            }
            dialog.Dispose();
            return fileName;
        }

        public static string ObtainSaveFilename(string sDialogTitle, string sFilter)
        {
            return ObtainSaveFilename(sDialogTitle, sFilter, null);
        }

        public static string ObtainSaveFilename(string sDialogTitle, string sFilter, string sInitialDirectory)
        {
            FileDialog dialog = new SaveFileDialog();
            dialog.Title = sDialogTitle;
            dialog.Filter = sFilter;
            if (!string.IsNullOrEmpty(sInitialDirectory))
            {
                dialog.InitialDirectory = sInitialDirectory;
                dialog.RestoreDirectory = true;
            }
            dialog.CustomPlaces.Add(CONFIG.GetPath("Captures"));
            string fileName = null;
            if (DialogResult.OK == dialog.ShowDialog(FiddlerApplication.UI))
            {
                fileName = dialog.FileName;
            }
            dialog.Dispose();
            return fileName;
        }

        [CodeDescription("Tokenize a string into tokens. Delimits on whitespace; \" marks are dropped unless preceded by \\ characters.")]
        public static string[] Parameterize(string sInput)
        {
            List<string> list = new List<string>();
            bool flag = false;
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < sInput.Length; i++)
            {
                switch (sInput[i])
                {
                    case ' ':
                    case '\t':
                        {
                            if (flag)
                            {
                                goto Label_00A1;
                            }
                            if ((builder.Length > 0) || ((i > 0) && (sInput[i - 1] == '"')))
                            {
                                list.Add(builder.ToString());
                                builder.Length = 0;
                            }
                            continue;
                        }
                    case '"':
                        {
                            if ((i <= 0) || (sInput[i - 1] != '\\'))
                            {
                                break;
                            }
                            builder.Remove(builder.Length - 1, 1);
                            builder.Append('"');
                            continue;
                        }
                    default:
                        goto Label_00B1;
                }
                flag = !flag;
                continue;
            Label_00A1:
                builder.Append(sInput[i]);
                continue;
            Label_00B1:
                builder.Append(sInput[i]);
            }
            if (builder.Length > 0)
            {
                list.Add(builder.ToString());
            }
            return list.ToArray();
        }

        public static NameValueCollection ParseQueryString(string sQuery)
        {
            return HttpUtility.ParseQueryString(sQuery);
        }

        internal static SslProtocols ParseSSLProtocolString(string sList)
        {
            SslProtocols none = SslProtocols.None;
            if (sList.IndexOf("ssl2", StringComparison.OrdinalIgnoreCase) > -1)
            {
                none |= SslProtocols.Ssl2;
            }
            if (sList.IndexOf("ssl3", StringComparison.OrdinalIgnoreCase) > -1)
            {
                none |= SslProtocols.Ssl3;
            }
            if (sList.IndexOf("tls1.0", StringComparison.OrdinalIgnoreCase) > -1)
            {
                none |= SslProtocols.Tls;
            }
            return none;
        }

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
        private static extern bool PathCompactPathEx(StringBuilder pszOut, string pszSrc, uint cchMax, uint dwFlags);
        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("shlwapi.dll", CharSet = CharSet.Auto)]
        private static extern bool PathUnExpandEnvStrings(string pszPath, [Out] StringBuilder pszBuf, int cchBuf);
        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("winmm.dll", SetLastError = true)]
        internal static extern bool PlaySound(string pszSound, IntPtr hMod, SoundFlags sf);
        [CodeDescription("Reads oStream until arrBytes is filled.")]
        public static int ReadEntireStream(Stream oStream, byte[] arrBytes)
        {
            int offset = 0;
            while (offset < arrBytes.LongLength)
            {
                offset += oStream.Read(arrBytes, offset, arrBytes.Length - offset);
            }
            return offset;
        }

        [CodeDescription("Load the specified .SAZ or .ZIP session archive")]
        public static Session[] ReadSessionArchive(string sFilename, bool bVerboseDialogs)
        {
            if (!System.IO.File.Exists(sFilename))
            {
                if (bVerboseDialogs)
                {
                    FiddlerApplication.DoNotifyUser("File " + sFilename + " does not exist.", "ReadSessionArchive Failed", MessageBoxIcon.Hand);
                }
                return null;
            }
            Application.DoEvents();
            ZipArchive archive = null;
            List<Session> list = new List<Session>();
            try
            {
                FileStream stream = System.IO.File.Open(sFilename, FileMode.Open, FileAccess.Read, FileShare.Read);
                if (((stream.Length < 0x40) || (stream.ReadByte() != 80)) || (stream.ReadByte() != 0x4b))
                {
                    if (bVerboseDialogs)
                    {
                        FiddlerApplication.DoNotifyUser(sFilename + " is not a Fiddler-generated .SAZ archive of HTTP Sessions.", "ReadSessionArchive Failed", MessageBoxIcon.Hand);
                    }
                    stream.Close();
                    return null;
                }
                stream.Close();
                archive = new ZipArchive(new DiskFile(sFilename));
                archive.BeginUpdate();
                AbstractFolder folder = archive.GetFolder("raw");
                if (!folder.Exists)
                {
                    if (bVerboseDialogs)
                    {
                        FiddlerApplication.DoNotifyUser("The selected file is not a Fiddler-generated .SAZ archive of HTTP Sessions.", "Invalid Archive", MessageBoxIcon.Hand);
                    }
                    archive.EndUpdate();
                    return null;
                }
                foreach (AbstractFile file in folder.GetFiles(true, new object[] { "*_c.txt" }))
                {
                    try
                    {
                        Stream stream2;
                        byte[] arrBytes = new byte[file.Size];
                    Label_010F:
                        try
                        {
                            stream2 = file.OpenRead(FileShare.Read);
                        }
                        catch (InvalidDecryptionPasswordException)
                        {
                            string str = frmPrompt.GetUserString("Password-Protected Session Archive", "Enter the password (case-sensitive) that will be used to decrypt this session archive file. Leave blank to abort open.", string.Empty);
                            if (!string.IsNullOrEmpty(str))
                            {
                                archive.DefaultDecryptionPassword = str;
                                goto Label_010F;
                            }
                            return null;
                        }
                        ReadEntireStream(stream2, arrBytes);
                        stream2.Close();
                        AbstractFile file2 = folder.GetFile(file.Name.Replace("_c.txt", "_s.txt"));
                        if (!file2.Exists)
                        {
                            if (bVerboseDialogs)
                            {
                                FiddlerApplication.DoNotifyUser("Could not find a server response. Missing file:\n" + file2.FullName, "Archive Incomplete", MessageBoxIcon.Hand);
                            }
                        }
                        else
                        {
                            byte[] buffer2 = new byte[file2.Size];
                            stream2 = file2.OpenRead();
                            ReadEntireStream(stream2, buffer2);
                            stream2.Close();
                            file2 = folder.GetFile(file.Name.Replace("_c.txt", "_m.xml"));
                            Session oS = new Session(arrBytes, buffer2);
                            if (file2.Exists)
                            {
                                oS.LoadMetadata(file2.OpenRead());
                            }
                            oS.oFlags["x-LoadedFrom"] = file.Name.Replace("_c.txt", "_s.txt");
                            if (oS.isAnyFlagSet(SessionFlags.IsWebSocketTunnel) && !oS.HTTPMethodIs("CONNECT"))
                            {
                                AbstractFile file3 = folder.GetFile(file.Name.Replace("_c.txt", "_w.txt"));
                                if (file3.Exists)
                                {
                                    WebSocket.LoadWebSocketMessagesFromStream(oS, file3.OpenRead());
                                }
                                else
                                {
                                    oS.oFlags["X-WS-SAZ"] = "SAZ File did not contain any WebSocket messages.";
                                }
                            }
                            list.Add(oS);
                        }
                    }
                    catch (Exception exception)
                    {
                        if (bVerboseDialogs)
                        {
                            FiddlerApplication.DoNotifyUser("Invalid data was present in Session: " + file.FullName + ".\n\n\n" + exception.Message + "\n" + exception.StackTrace, "Archive Incomplete", MessageBoxIcon.Hand);
                        }
                    }
                }
            }
            catch (Exception exception2)
            {
                FiddlerApplication.ReportException(exception2);
                return null;
            }
            if (archive != null)
            {
                archive.EndUpdate();
                archive = null;
                if (FiddlerApplication.Prefs.GetBoolPref("fiddler.saz.ClearCaches", false))
                {
                    ZipArchive.ClearCachedZipHandlers();
                }
            }
            return list.ToArray();
        }

        internal static string RegExEscape(string sString, bool bAddPrefixCaret, bool bAddSuffixDollarSign)
        {
            StringBuilder builder = new StringBuilder();
            if (bAddPrefixCaret)
            {
                builder.Append("^");
            }
            foreach (char ch in sString)
            {
                switch (ch)
                {
                    case '#':
                    case '$':
                    case '(':
                    case ')':
                    case '+':
                    case '.':
                    case '?':
                    case '[':
                    case '\\':
                    case '^':
                    case '{':
                    case '|':
                        builder.Append('\\');
                        break;

                    case '*':
                        builder.Append('.');
                        break;
                }
                builder.Append(ch);
            }
            if (bAddSuffixDollarSign)
            {
                builder.Append('$');
            }
            return builder.ToString();
        }

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll")]
        internal static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
        public static bool RunExecutable(string sExecute, string sParams)
        {
            try
            {
                using (Process.Start(sExecute, sParams))
                {
                }
                return true;
            }
            catch (Exception exception)
            {
                if (!(exception is Win32Exception) || (0x4c7 != (exception as Win32Exception).NativeErrorCode))
                {
                    FiddlerApplication.DoNotifyUser(string.Format("Failed to execute: {0}\r\n{1}\r\n\r\n{2}\r\n{3}", new object[] { sExecute, string.IsNullOrEmpty(sParams) ? string.Empty : ("with parameters: " + sParams), exception.Message, exception.StackTrace.ToString() }), "ShellExecute Failed");
                }
            }
            return false;
        }

        [CodeDescription("Run an executable and wait for it to exit.")]
        public static bool RunExecutableAndWait(string sExecute, string sParams)
        {
            try
            {
                Process process = new Process();
                process.StartInfo.FileName = sExecute;
                process.StartInfo.Arguments = sParams;
                process.Start();
                process.WaitForExit();
                process.Dispose();
                return true;
            }
            catch (Exception exception)
            {
                if (!(exception is Win32Exception) || (0x4c7 != (exception as Win32Exception).NativeErrorCode))
                {
                    FiddlerApplication.DoNotifyUser("Fiddler Exception thrown: " + exception.ToString() + "\r\n" + exception.StackTrace.ToString(), "ShellExecute Failed");
                }
                return false;
            }
        }

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll", EntryPoint = "SendMessage")]
        private static extern bool SendCueTextMessage(IntPtr hWnd, int msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);
        [DllImport("user32.dll")]
        internal static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll", EntryPoint = "SendMessage")]
        internal static extern IntPtr SendWMCopyMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref SendDataStruct lParam);
        public static void SetCueText(Control oCtl, string sText)
        {
            IntPtr hwndItem;
            if (oCtl is ComboBox)
            {
                if (Environment.OSVersion.Version.Major >= 6)
                {
                    SendCueTextMessage(oCtl.Handle, 0x1703, IntPtr.Zero, sText);
                    return;
                }
                hwndItem = GetComboBoxInfo(oCtl).hwndItem;
            }
            else
            {
                hwndItem = oCtl.Handle;
            }
            SendCueTextMessage(hwndItem, 0x1501, IntPtr.Zero, sText);
        }

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll")]
        internal static extern bool SetForegroundWindow(IntPtr hWnd);
        [CodeDescription("Save a string to the registry. Correctly handles null Value, saving as String.Empty.")]
        public static void SetRegistryString(RegistryKey oReg, string sName, string sValue)
        {
            if (sName != null)
            {
                if (sValue == null)
                {
                    sValue = string.Empty;
                }
                oReg.SetValue(sName, sValue);
            }
        }

        [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
        private static extern int SHOpenWithDialog(IntPtr hWndParent, ref tagOPENASINFO oOAI);
        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll")]
        internal static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
        internal static string StringToCF_HTML(string inStr)
        {
            string str = "<HTML><HEAD><STYLE>.REQUEST { font: 8pt Courier New; color: blue;} .RESPONSE { font: 8pt Courier New; color: green;}</STYLE></HEAD><BODY>" + inStr + "</BODY></HTML>";
            string format = "Version:1.0\r\nStartHTML:{0:00000000}\r\nEndHTML:{1:00000000}\r\nStartFragment:{0:00000000}\r\nEndFragment:{1:00000000}\r\n";
            return (string.Format(format, format.Length - 0x10, (str.Length + format.Length) - 0x10) + str);
        }

        [CodeDescription("Returns the part of a string up to (but NOT including) the first instance of specified delimiter. If delim not found, returns entire string.")]
        public static string TrimAfter(string sString, char chDelim)
        {
            if (sString == null)
            {
                return string.Empty;
            }
            int index = sString.IndexOf(chDelim);
            if (index < 0)
            {
                return sString;
            }
            return sString.Substring(0, index);
        }

        public static string TrimAfter(string sString, int iMaxLength)
        {
            return TrimTo(sString, iMaxLength);
        }

        [CodeDescription("Returns the part of a string up to (but NOT including) the first instance of specified substring. If delim not found, returns entire string.")]
        public static string TrimAfter(string sString, string sDelim)
        {
            if (sString == null)
            {
                return string.Empty;
            }
            if (sDelim == null)
            {
                return sString;
            }
            int index = sString.IndexOf(sDelim);
            if (index < 0)
            {
                return sString;
            }
            return sString.Substring(0, index);
        }

        [CodeDescription("Returns the part of a string after (but NOT including) the first instance of specified delimiter. If delim not found, returns entire string.")]
        public static string TrimBefore(string sString, char chDelim)
        {
            if (sString == null)
            {
                return string.Empty;
            }
            int index = sString.IndexOf(chDelim);
            if (index < 0)
            {
                return sString;
            }
            return sString.Substring(index + 1);
        }

        [CodeDescription("Returns the part of a string after (but NOT including) the first instance of specified substring. If delim not found, returns entire string.")]
        public static string TrimBefore(string sString, string sDelim)
        {
            if (sString == null)
            {
                return string.Empty;
            }
            if (sDelim == null)
            {
                return sString;
            }
            int index = sString.IndexOf(sDelim);
            if (index < 0)
            {
                return sString;
            }
            return sString.Substring(index + sDelim.Length);
        }

        [CodeDescription("Returns the part of a string after (but not including) the last instance of specified delimiter. If delim not found, returns entire string.")]
        public static string TrimBeforeLast(string sString, char chDelim)
        {
            if (sString == null)
            {
                return string.Empty;
            }
            int num = sString.LastIndexOf(chDelim);
            if (num < 0)
            {
                return sString;
            }
            return sString.Substring(num + 1);
        }

        [CodeDescription("Returns the part of a string after (but not including) the last instance of specified substring. If delim not found, returns entire string.")]
        public static string TrimBeforeLast(string sString, string sDelim)
        {
            if (sString == null)
            {
                return string.Empty;
            }
            if (sDelim == null)
            {
                return sString;
            }
            int num = sString.LastIndexOf(sDelim);
            if (num < 0)
            {
                return sString;
            }
            return sString.Substring(num + sDelim.Length);
        }

        [CodeDescription("Returns the first iMaxLength or fewer characters from the target string.")]
        public static string TrimTo(string sString, int iMaxLength)
        {
            if (string.IsNullOrEmpty(sString))
            {
                return string.Empty;
            }
            if (iMaxLength >= sString.Length)
            {
                return sString;
            }
            return sString.Substring(0, iMaxLength);
        }

        [CodeDescription("Returns the part of a string after (and including) the first instance of specified substring. If delim not found, returns entire string.")]
        public static string TrimUpTo(string sString, string sDelim)
        {
            if (sString == null)
            {
                return string.Empty;
            }
            if (sDelim == null)
            {
                return sString;
            }
            int index = sString.IndexOf(sDelim);
            if (index < 0)
            {
                return sString;
            }
            return sString.Substring(index);
        }

        [CodeDescription("Try parsing the string for a Hex-formatted int. If it fails, return false and 0 in iOutput.")]
        public static bool TryHexParse(string sInput, out int iOutput)
        {
            return int.TryParse(sInput, NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo, out iOutput);
        }

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll")]
        internal static extern bool UnregisterHotKey(IntPtr hWnd, int id);
        public static string UrlDecode(string sInput)
        {
            return UrlDecode(sInput, Encoding.UTF8);
        }

        public static string UrlDecode(string sInput, Encoding oEnc)
        {
            return HttpUtility.UrlDecode(sInput, oEnc);
        }

        public static byte[] UrlDecodeToBytes(string sInput, Encoding oEnc)
        {
            return HttpUtility.UrlDecodeToBytes(sInput, oEnc);
        }

        public static string UrlEncode(string sInput)
        {
            return UrlEncodeChars(sInput, Encoding.UTF8);
        }

        public static string UrlEncode(string sInput, Encoding oEnc)
        {
            return UrlEncodeChars(sInput, oEnc);
        }

        private static string UrlEncodeChars(string str, Encoding oEnc)
        {
            if (string.IsNullOrEmpty(str))
            {
                return str;
            }
            StringBuilder builder = new StringBuilder();
            foreach (char ch in str)
            {
                if ((((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))) || (((ch >= '0') && (ch <= '9')) || ((((ch == '-') || (ch == '.')) || ((ch == '(') || (ch == ')'))) || (((ch == '*') || (ch == '\'')) || ((ch == '_') || (ch == '!'))))))
                {
                    builder.Append(ch);
                }
                else if (ch == ' ')
                {
                    builder.Append("+");
                }
                else
                {
                    foreach (byte num in oEnc.GetBytes(new char[] { ch }))
                    {
                        builder.Append("%");
                        builder.Append(num.ToString("X2"));
                    }
                }
            }
            return builder.ToString();
        }

        public static string UrlPathEncode(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return str;
            }
            int index = str.IndexOf('?');
            if (index >= 0)
            {
                return (UrlPathEncode(str.Substring(0, index)) + str.Substring(index));
            }
            return UrlPathEncodeChars(str);
        }

        private static string UrlPathEncodeChars(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return str;
            }
            StringBuilder builder = new StringBuilder();
            foreach (char ch in str)
            {
                if ((ch > ' ') && (ch < '\x007f'))
                {
                    builder.Append(ch);
                }
                else if (ch < '!')
                {
                    builder.Append("%");
                    builder.Append(((byte)ch).ToString("X2"));
                }
                else
                {
                    foreach (byte num in Encoding.UTF8.GetBytes(new char[] { ch }))
                    {
                        builder.Append("%");
                        builder.Append(num.ToString("X2"));
                    }
                }
            }
            return builder.ToString();
        }

        public static void utilDecodeHTTPBody(HTTPHeaders oHeaders, ref byte[] arrBody)
        {
            if ((arrBody != null) && (arrBody.LongLength > 0))
            {
                _DecodeInOrder(oHeaders["Transfer-Encoding"], true, ref arrBody);
                _DecodeInOrder(oHeaders["Content-Encoding"], false, ref arrBody);
            }
        }

        [CodeDescription("Writes arrBytes to a file, creating the target directory and overwriting if the file exists.")]
        public static void WriteArrayToFile(string sFilename, byte[] arrBytes)
        {
            if (arrBytes == null)
            {
                arrBytes = new byte[0];
            }
            EnsureOverwritable(sFilename);
            System.IO.File.WriteAllBytes(sFilename, arrBytes);
        }

        internal static void WriteODCXML(DiskFile odfZip)
        {
            Stream stream = new ZippedFile(odfZip, "[Content_Types].xml").CreateWrite(FileShare.None);
            byte[] bytes = Encoding.UTF8.GetBytes("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">\r\n<Default Extension=\"htm\" ContentType=\"text/html\" />\r\n<Default Extension=\"xml\" ContentType=\"application/xml\" />\r\n<Default Extension=\"txt\" ContentType=\"text/plain\" />\r\n</Types>");
            stream.Write(bytes, 0, bytes.Length);
            stream.Close();
        }

        [CodeDescription("Save the specified .SAZ session archive")]
        public static bool WriteSessionArchive(string sFilename, Session[] arrSessions, string sPassword, bool bVerboseDialogs)
        {
            if ((arrSessions == null) || (arrSessions.Length < 1))
            {
                if (bVerboseDialogs)
                {
                    FiddlerApplication.DoNotifyUser("No sessions were provided to save to the archive.", "WriteSessionArchive - No Input");
                }
                return false;
            }
            try
            {
                if (System.IO.File.Exists(sFilename))
                {
                    System.IO.File.Delete(sFilename);
                }
                DiskFile zipFile = new DiskFile(sFilename);
                ZipArchive archive = new ZipArchive(zipFile);
                if (FiddlerApplication.Prefs.GetBoolPref("fiddler.SAZ.UseMemoryCache", true))
                {
                    archive.TempFolder = new MemoryFolder();
                }
                archive.BeginUpdate();
                WriteODCXML(zipFile);
                ZippedFolder folder1 = (ZippedFolder)archive.CreateFolder("raw");
                if (!string.IsNullOrEmpty(sPassword))
                {
                    if (CONFIG.bUseAESForSAZ)
                    {
                        archive.DefaultEncryptionMethod = EncryptionMethod.WinZipAes;
                        if (!FiddlerApplication.Prefs.GetBoolPref("fiddler.saz.AES.Use256Bit", false))
                        {
                            archive.DefaultEncryptionStrength = 0x80;
                        }
                    }
                    archive.DefaultEncryptionPassword = sPassword;
                }
                archive.Comment = "Fiddler (v" + Application.ProductVersion + ") Session Archive. See http://www.fiddler2.com";
                int iFileNumber = 1;
                int length = arrSessions.Length;
                string sFileNumberFormat = "D" + length.ToString().Length;
                foreach (Session session in arrSessions)
                {
                    WriteSessionToSAZ(session, zipFile, iFileNumber, sFileNumberFormat, null, bVerboseDialogs);
                    iFileNumber++;
                }
                archive.EndUpdate();
                if (FiddlerApplication.Prefs.GetBoolPref("fiddler.saz.ClearCaches", false))
                {
                    ZipArchive.ClearCachedZipHandlers();
                }
                return true;
            }
            catch (Exception exception)
            {
                if (bVerboseDialogs)
                {
                    FiddlerApplication.DoNotifyUser("Failed to save Session Archive.\n\n" + exception.Message, "Save Failed");
                }
                return false;
            }
        }

        internal static void WriteSessionToSAZ(Session oSession, DiskFile odfZip, int iFileNumber, string sFileNumberFormat, StringBuilder sbHTML, bool bVerboseDialogs)
        {
            string str = @"raw\" + iFileNumber.ToString(sFileNumberFormat);
            string fileName = str + "_c.txt";
            string str3 = str + "_s.txt";
            string str4 = str + "_m.xml";
            try
            {
                ZippedFile file = new ZippedFile(odfZip, fileName);
                using (Stream stream = file.CreateWrite(FileShare.None))
                {
                    oSession.WriteRequestToStream(false, true, stream);
                }
            }
            catch (Exception exception)
            {
                if (bVerboseDialogs)
                {
                    FiddlerApplication.DoNotifyUser("Unable to add " + fileName + "\n\n" + exception.Message, "Archive Failure");
                }
            }
            try
            {
                ZippedFile file2 = new ZippedFile(odfZip, str3);
                using (Stream stream2 = file2.CreateWrite(FileShare.None))
                {
                    oSession.WriteResponseToStream(stream2, false);
                }
            }
            catch (Exception exception2)
            {
                if (bVerboseDialogs)
                {
                    FiddlerApplication.DoNotifyUser("Unable to add " + str3 + "\n\n" + exception2.Message, "Archive Failure");
                }
            }
            try
            {
                ZippedFile file3 = new ZippedFile(odfZip, str4);
                using (Stream stream3 = file3.CreateWrite(FileShare.None))
                {
                    oSession.WriteMetadataToStream(stream3);
                }
            }
            catch (Exception exception3)
            {
                if (bVerboseDialogs)
                {
                    FiddlerApplication.DoNotifyUser("Unable to add " + str4 + "\n\n" + exception3.Message, "Archive Failure");
                }
            }
            if (oSession.bHasWebSocketMessages)
            {
                string str5 = str + "_w.txt";
                try
                {
                    ZippedFile file4 = new ZippedFile(odfZip, str5);
                    using (Stream stream4 = file4.CreateWrite(FileShare.None))
                    {
                        oSession.WriteWebSocketMessagesToStream(stream4);
                    }
                }
                catch (Exception exception4)
                {
                    if (bVerboseDialogs)
                    {
                        FiddlerApplication.DoNotifyUser("Unable to add " + str5 + "\n\n" + exception4.Message, "Archive Failure");
                    }
                }
            }
            if (sbHTML != null)
            {
                sbHTML.Append("<tr>");
                sbHTML.AppendFormat("<TD><a href='{0}'>C</a>&nbsp;", fileName);
                sbHTML.AppendFormat("<a href='{0}'>S</a>&nbsp;", str3);
                sbHTML.AppendFormat("<a href='{0}'>M</a>", str4);
                if (oSession.bHasWebSocketMessages)
                {
                    sbHTML.AppendFormat("&nbsp;<a href='{0}_w.txt'>W</a>", str);
                }
                sbHTML.AppendFormat("</TD>", new object[0]);
                ListViewItem viewItem = oSession.ViewItem;
                if (viewItem != null)
                {
                    ListViewItem.ListViewSubItemCollection subItems = viewItem.SubItems;
                    if (subItems != null)
                    {
                        foreach (ListViewItem.ListViewSubItem item2 in subItems)
                        {
                            sbHTML.AppendFormat("<td>{0}</td>", HtmlEncode(item2.Text));
                        }
                    }
                }
                sbHTML.Append("</tr>");
            }
        }

        public static byte[] ZLibExpand(byte[] compressedData)
        {
            if ((compressedData == null) || (compressedData.Length == 0))
            {
                return new byte[0];
            }
            try
            {
                MemoryStream inner = new MemoryStream(compressedData);
                MemoryStream stream2 = new MemoryStream(compressedData.Length);
                using (ZLibCompressedStream stream3 = new ZLibCompressedStream(inner, CompressionMethod.Deflated, CompressionLevel.Highest))
                {
                    byte[] buffer = new byte[0x8000];
                    int count = 0;
                    while ((count = stream3.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        stream2.Write(buffer, 0, count);
                    }
                }
                return stream2.ToArray();
            }
            catch (Exception exception)
            {
                FiddlerApplication.DoNotifyUser("The content could not be decompressed.\n\n" + exception.Message, "Fiddler: ZLib Inflation failed");
                return new byte[0];
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct COMBOBOXINFO
        {
            public int cbSize;
            public Utilities.RECT rcItem;
            public Utilities.RECT rcButton;
            public int stateButton;
            public IntPtr hwndCombo;
            public IntPtr hwndItem;
            public IntPtr hwndList;
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            public IntPtr lpData;
        }

        [Flags]
        private enum FlashWInfo : uint
        {
            FLASHW_ALL = 3,
            FLASHW_CAPTION = 1,
            FLASHW_STOP = 0,
            FLASHW_TIMER = 4,
            FLASHW_TIMERNOFG = 12,
            FLASHW_TRAY = 2
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct FLASHWINFO
        {
            public int cbSize;
            public IntPtr hwnd;
            public Utilities.FlashWInfo dwFlags;
            public int uCount;
            public int dwTimeout;
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct RECT
        {
            internal int Left;
            internal int Top;
            internal int Right;
            internal int Bottom;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        internal struct SendDataStruct
        {
            public IntPtr dwData;
            public int cbData;
            public string strData;
        }

        [Flags]
        internal enum SoundFlags : uint
        {
            SND_ALIAS = 0x10000,
            SND_ALIAS_ID = 0x110000,
            SND_ASYNC = 1,
            SND_FILENAME = 0x20000,
            SND_LOOP = 8,
            SND_MEMORY = 4,
            SND_NODEFAULT = 2,
            SND_NOSTOP = 0x10,
            SND_NOWAIT = 0x2000,
            SND_RESOURCE = 0x40004,
            SND_SYNC = 0
        }

        [Flags]
        private enum tagOPEN_AS_INFO_FLAGS
        {
            OAIF_ALLOW_REGISTRATION = 1,
            OAIF_EXEC = 4,
            OAIF_FILE_IS_URI = 0x80,
            OAIF_FORCE_REGISTRATION = 8,
            OAIF_HIDE_REGISTRATION = 0x20,
            OAIF_REGISTER_EXT = 2,
            OAIF_URL_PROTOCOL = 0x40
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct tagOPENASINFO
        {
            [MarshalAs(UnmanagedType.LPWStr)]
            public string cszFile;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string cszClass;
            [MarshalAs(UnmanagedType.I4)]
            public Utilities.tagOPEN_AS_INFO_FLAGS oaifInFlags;
        }
    }
}

